package com.dustedpixels.jasmin.chips.z80.impl;

import jasmin.impl.Z80Impl;
import jasmin.inter.IOBus;
import jasmin.inter.Memory;
import jasmin.inter.Z80;
import jasmin.inter.Z80InterruptMode;
import jasmin.inter.Z80Socket;

import com.dustedpixels.jasmin.chips.z80.Z80Context;
import com.dustedpixels.jasmin.chips.z80.implbase.Z80ImplBase;

public final class Z80Version1 extends Z80ImplBase {
    private final Z80Impl impl;

    public Z80Version1(final Z80Context context) {
        this.impl = new Z80Impl();

        final IOBus ioBus = new IOBus() {
            public int in(int port) {
                return context.in((short) port) & 0xFF;
            }

            public void out(int port, int value) {
                context.out((short) port, (byte) value);
            }
        };
        
        final Memory memory = new Memory() {
            public int peek(int address) {
                return context.peek((short) address) & 0xFF;
            }

            public void poke(int address, int value) {
                context.poke((short) address, (byte) value);
            }
        };
        
        final Z80Socket socket = new Z80Socket() {
            public IOBus getIOBus() {
                return ioBus;
            }

            public Memory getMemory() {
                return memory;
            }

            public Z80 getZ80() {
                return impl;
            }

            public void plug(Z80 z80) {
                z80.plugCallback(this);
            }            
        };
        
        socket.plug(impl);
    }

    public byte getA() {
        return (byte) impl.getDirectRegisterPack().A().get();
    }

    public byte getA2() {
        return (byte) impl.getDirectRegisterPack().A_BIS().get();
    }

    public byte getB() {
        return (byte) impl.getDirectRegisterPack().B().get();
    }

    public byte getB2() {
        return (byte) impl.getDirectRegisterPack().B_BIS().get();
    }

    public byte getC() {
        return (byte) impl.getDirectRegisterPack().C().get();
    }

    public byte getC2() {
        return (byte) impl.getDirectRegisterPack().C_BIS().get();
    }

    public long getCycles() {
        return impl.getCycles();
    }

    public byte getD() {
        return (byte) impl.getDirectRegisterPack().D().get();
    }

    public byte getD2() {
        return (byte) impl.getDirectRegisterPack().D_BIS().get();
    }

    public byte getE() {
        return (byte) impl.getDirectRegisterPack().E().get();
    }

    public byte getE2() {
        return (byte) impl.getDirectRegisterPack().E_BIS().get();
    }

    public byte getF() {
        return (byte) impl.getDirectRegisterPack().F().get();
    }

    public byte getF2() {
        return (byte) impl.getDirectRegisterPack().F_BIS().get();
    }

    public byte getH() {
        return (byte) impl.getDirectRegisterPack().H().get();
    }

    public byte getH2() {
        return (byte) impl.getDirectRegisterPack().H_BIS().get();
    }

    public byte getI() {
        return (byte) impl.getDirectRegisterPack().I().get();
    }

    public boolean getIFF1() {
        return impl.getDirectRegisterPack().IFF1().get();
    }

    public boolean getIFF2() {
        return impl.getDirectRegisterPack().IFF2().get();
    }

    public byte getIM() {
        return (byte) impl.getDirectRegisterPack().IM().get().getNumber();
    }

    public short getIX() {
        return (short) impl.getDirectRegisterPack().IX().get();
    }

    public short getIY() {
        return (short) impl.getDirectRegisterPack().IY().get();
    }

    public byte getL() {
        return (byte) impl.getDirectRegisterPack().L().get();
    }

    public byte getL2() {
        return (byte) impl.getDirectRegisterPack().L_BIS().get();
    }

    public short getPC() {
        return (short) impl.getDirectRegisterPack().PC().get();
    }

    public byte getR() {
        return (byte) impl.getDirectRegisterPack().R().get();
    }

    public short getSP() {
        return (short) impl.getDirectRegisterPack().SP().get();
    }

    public void processInstruction() {
        impl.processSlice();
    }

    public void setA(byte value) {
        impl.getDirectRegisterPack().A().set(value & 0xFF);
    }

    public void setA2(byte value) {
        impl.getDirectRegisterPack().A_BIS().set(value & 0xFF);
    }

    public void setB(byte value) {
        impl.getDirectRegisterPack().B().set(value & 0xFF);
    }

    public void setB2(byte value) {
        impl.getDirectRegisterPack().B_BIS().set(value & 0xFF);
    }

    public void setC(byte value) {
        impl.getDirectRegisterPack().C().set(value & 0xFF);
    }

    public void setC2(byte value) {
        impl.getDirectRegisterPack().C_BIS().set(value & 0xFF);
    }

    public void setD(byte value) {
        impl.getDirectRegisterPack().D().set(value & 0xFF);
    }

    public void setD2(byte value) {
        impl.getDirectRegisterPack().D_BIS().set(value & 0xFF);
    }

    public void setE(byte value) {
        impl.getDirectRegisterPack().E().set(value & 0xFF);
    }

    public void setE2(byte value) {
        impl.getDirectRegisterPack().E_BIS().set(value & 0xFF);
    }

    public void setF(byte value) {
        impl.getDirectRegisterPack().F().set(value & 0xFF);
    }

    public void setF2(byte value) {
        impl.getDirectRegisterPack().F_BIS().set(value & 0xFF);
    }

    public void setH(byte value) {
        impl.getDirectRegisterPack().H().set(value & 0xFF);
    }

    public void setH2(byte value) {
        impl.getDirectRegisterPack().H_BIS().set(value & 0xFF);
    }

    public void setI(byte value) {
        impl.getDirectRegisterPack().I().set(value & 0xFF);
    }

    public void setIFF1(boolean value) {
        impl.getDirectRegisterPack().IFF1().set(value);
    }

    public void setIFF2(boolean value) {
        impl.getDirectRegisterPack().IFF2().set(value);
    }

    public void setIM(byte value) {
        impl.getDirectRegisterPack().IM().set(Z80InterruptMode.forNumber(value));
    }

    public void setIX(short value) {
        impl.getDirectRegisterPack().IX().set(value & 0xFFFF);
    }

    public void setIY(short value) {
        impl.getDirectRegisterPack().IY().set(value & 0xFFFF);
    }

    public void setL(byte value) {
        impl.getDirectRegisterPack().L().set(value & 0xFF);
    }

    public void setL2(byte value) {
        impl.getDirectRegisterPack().L_BIS().set(value & 0xFF);
    }

    public void setPC(short value) {
        impl.getDirectRegisterPack().PC().set(value & 0xFFFF);
    }

    public void setR(byte value) {
        impl.getDirectRegisterPack().R().set(value & 0xFF);
    }

    public void setSP(short value) {
        impl.getDirectRegisterPack().SP().set(value & 0xFFFF);
    }
}
